package com.lw.sbdemo2.common.web.json;

import com.alibaba.fastjson.JSONObject;
import com.lw.sbdemo2.common.exception.ApiException;
import com.lw.sbdemo2.common.exception.ResponseCodeEnum;
import com.lw.sbdemo2.common.utils.ValidUtil;
import com.lw.sbdemo2.common.web.anno.RequestJson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.BufferedReader;
import javax.servlet.http.HttpServletRequest;

/**
 * <p>标题: @RequestJson 参数解析器 </p>
 * <p>描述: 用于ContentType为JSON时，从BODY-JSON字符串获取单个属性，单个方法该注解不建议使用多次</p>
 * <p>版权: Copyright (c) 2018</p>
 * <p>公司: 智业软件</p>
 *
 * @author LinWang
 * @date 2018-05-09 16:07
 */
@Slf4j
public class RequestJsonArgResolver implements HandlerMethodArgumentResolver {

    /**
     * 用于判定是否需要处理该参数分解，返回true为需要，并会去调用下面的方法resolveArgument
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RequestJson.class);
    }

    /**
     * 真正用于处理参数分解的方法，返回的Object就是controller方法上的形参对象
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        //获取注解信息
        RequestJson requestJson = parameter.getParameterAnnotation(RequestJson.class);
        String value = requestJson.value();
        if (StringUtils.isEmpty(value)) {
            value = parameter.getParameterName();
        }

        //重新获取request
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        BufferedReader reader = request.getReader();
        StringBuilder sb = new StringBuilder();
        char[] buf = new char[1024];
        int rd;
        while ((rd = reader.read(buf)) != -1) {
            sb.append(buf, 0, rd);
        }

        //处理结果
        Object result;
        JSONObject jsonObject = JSONObject.parseObject(sb.toString());

        if (jsonObject != null) {
            result = jsonObject.get(value);
        } else {
            result = null;
        }

        if (ValidUtil.isEmptyOrNull(result)) {
            throw new ApiException(ResponseCodeEnum.EX_PARAM, value);
        }

        log.info("RequestJson 注释处理 ，key：{}，result:{}", value, result);

        return result;
    }
}